package com.yunxi.module.system.service.social.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
import com.google.common.annotations.VisibleForTesting;
import com.xingyuv.jushauth.config.AuthConfig;
import com.xingyuv.jushauth.model.AuthCallback;
import com.xingyuv.jushauth.model.AuthResponse;
import com.xingyuv.jushauth.model.AuthUser;
import com.xingyuv.jushauth.request.AuthRequest;
import com.xingyuv.justauth.AuthRequestFactory;
import com.yunxi.framework.common.enums.CommonStatusEnum;
import com.yunxi.module.system.model.social.SocialClientDO;
import com.yunxi.module.system.enums.social.SocialTypeEnum;
import com.yunxi.module.system.mapper.social.SocialClientMapper;
import com.yunxi.module.system.service.social.SocialClientService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;

import static com.yunxi.framework.common.util.json.JsonUtils.toJsonString;

/**
 * <p>
 * 社交应用 Service 接口实现类
 * </p>
 *
 * @author lidy
 * @since 2024-05-08
 */
@Service
@Slf4j
public class SocialClientServiceImpl implements SocialClientService {

    @Resource
    private AuthRequestFactory authRequestFactory;

    @Resource
    private SocialClientMapper socialClientMapper;

    /**
     * 请求社交平台，获得授权的用户
     *
     * @param socialType 社交平台类型
     * @param userType   用户类型
     * @param code       授权码
     * @param state      授权 state
     * @return 授权的用户
     */
    @Override
    public AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state) {
        // 构建请求
        AuthRequest authRequest = buildAuthRequest(socialType, userType);
        AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build();

        // 执行请求
        AuthResponse<?> authResponse = authRequest.login(authCallback);
        log.info("[getAuthUser][氢气社交平台 type({}) request({}) response({})]", socialType, toJsonString(authCallback), toJsonString(authRequest));
        return (AuthUser) authResponse.getData();
    }

    /**
     * 构建 AuthRequest 对象，支持多租户配置
     *
     * @param socialType 社交类型
     * @param userType   用户类型
     * @return AuthRequest 对象
     */
    @VisibleForTesting
    private AuthRequest buildAuthRequest(Integer socialType, Integer userType) {
        // 1.先查找默认的配置项，从 application-*.yaml 中读取
        AuthRequest request = authRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource());
        Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType));

        // 2.查询数据库的配置项，如果存在则进行覆盖
        SocialClientDO clientDO = socialClientMapper.selectBySocialTypeAndUserType(socialType, userType);
        if (clientDO != null && Objects.equals(clientDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            // 2.1 构造新的 AuthConfig 对象
            AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(request, "config");
            AuthConfig newAuthConfig = ReflectUtil.newInstance(authConfig.getClass());
            BeanUtil.copyProperties(authConfig, newAuthConfig);

            // 2.2 修改对应的 clientId + clientSecret 秘钥
            newAuthConfig.setClientId(clientDO.getClientId());
            newAuthConfig.setClientSecret(clientDO.getClientSecret());
            if (clientDO.getAgentId() != null) {
                // 如果有 agentID 则修改 agentID
                newAuthConfig.setAgentId(clientDO.getAgentId());
            }
            // 2.3 设置回 request 里，进行后续使用
            ReflectUtil.setFieldValue(request, "config", newAuthConfig);
        }
        return request;
    }
}
